package com.ydj.framework.filter;

import com.ydj.framework.interceptor.InterceptorContext;
import com.ydj.framework.utils.IpUtils;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.ThreadContext;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class HttpServletRequestWrapperFilter implements Filter {
	private static AtomicInteger sRequestSeq = new AtomicInteger(0);

	@Override
	public void init(FilterConfig filterConfig) {
	}

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;

		// 打log用的
		ThreadContext.put("userId", "未登录");
		ThreadContext.put("ip", IpUtils.getIpAddr(request));

		if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
			return;
		}

		// 如果是 Nginx 的请求，就不要加 1 了，反正也不会打印出来
		int requestId;
		if ("/common/check".equalsIgnoreCase(request.getRequestURI())) {
			requestId = sRequestSeq.get();
		} else {
			// 不用担心一直加到int的最大值。到最大值之后，会变成负数继续加下去的
			requestId = sRequestSeq.incrementAndGet();
		}

		// 记录耗时
		long startTime = System.currentTimeMillis();
		ExtHttpServletResponse extResponse = new ExtHttpServletResponse(response);
		ExtHttpServletRequest extRequest = null;

		String contentType = request.getContentType();
		if (StringUtils.isNotBlank(contentType)) {
			String[] contentTypes = contentType.split(";");
			for (String type : contentTypes) {
				switch (type) {
					// 上传文件
					case "multipart/form-data":
						extRequest = new ExtHttpServletRequest(new StandardMultipartHttpServletRequest(request), requestId);
						break;
				}

				if (extRequest != null) {
					break;
				}
			}
		}

		if (extRequest == null) {
			extRequest = new ExtHttpServletRequest(request, requestId);
		}

		chain.doFilter(extRequest, extResponse);

		// 打印LOG
		ApiOperation functionName = extRequest.getInterceptorContext().getFunctionNameAnnotation();
		if (functionName != null && !functionName.hidden()) {
			boolean printResponse = extRequest.getInterceptorContext().getLogPrinterAnnotation() == null ? true : extRequest.getInterceptorContext().getLogPrinterAnnotation().response();
			long costTime = System.currentTimeMillis() - startTime;
			logResponse(extRequest, extResponse, costTime, printResponse);
		}

		// 真正的输出客户端
		extResponse.outputToClient();
	}

	@Override
	public void destroy() {
	}

	private void logResponse(ExtHttpServletRequest extRequest, ExtHttpServletResponse extResponse, long time, boolean printResponse) throws IOException {
		// 请求
		String req = extRequest.getRequestStringForLog();
		if (StringUtils.isBlank(req)) {
			req = "{}";
		}

		// 响应
		String res;
		if (printResponse) {
			String buffer = extResponse.getResponseDataToPrintLog();
			if (buffer.length() > 10 * 1024) {
				res = buffer.substring(0, 10 * 1024);
			} else {
				res = buffer;
			}
		} else {
			res = "不打印";
		}

		// 函数名字
		InterceptorContext context = extRequest.getInterceptorContext();
		ApiOperation functionReadme = context.getFunctionNameAnnotation();
		String functionName = functionReadme == null ? "没有ApiOperation" : functionReadme.value();
		String url = extRequest.getRequestURI();
//		String showId = context.getRdsLoginInfo() == null ? "无" : context.getRdsLoginInfo().getIdForLog();
		String showName = context.getRdsLoginInfo() == null ? "无" : context.getRdsLoginInfo().getNameForLog();
		int requestId = extRequest.getRequestId();

		log.info("响应{}【{}】({}) 耗时:{}ms, 用户:{}, 响应体:{}, 请求体:{}", requestId, functionName, url, time, showName, res, req);
	}
}